package com.sneakxy.mybatis.commons.properties;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
import java.util.stream.Stream;

import org.apache.ibatis.type.JdbcType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.sneakxy.mybatis.commons.dialect.Dialect;
import com.sneakxy.mybatis.commons.dialect.DialectFactory;
import com.sneakxy.mybatis.commons.repository.config.MybatisCommonsConfiguration;
import com.sneakxy.mybatis.commons.utils.SnowflakeIdGenerator;

@ConfigurationProperties(prefix = SpringDataMybatisProperties.CONFIG_PREFIX)
public class SpringDataMybatisProperties {

	private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
	
	public static final String CONFIG_PREFIX = "spring.data.mybatis";
	
	private String dialect;
	
	private JdbcType jdbcTypeForNull;
	
	private String[] mappersLocations;
	
	private Snowflake snowflake = new Snowflake();
	
	public Resource[] resolveMapperLocations() {
        return Stream.of(Optional.ofNullable(this.mappersLocations).orElse(new String[0]))
        		 .flatMap(location -> Stream.of(getResources(location)))
                 .toArray(Resource[]::new);
    }
	
	public Dialect resolveDialect(MybatisCommonsConfiguration configuration) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		return DialectFactory.getDialect(configuration, getDialect());
	}
	
	private Resource[] getResources(String location) {
        try {
            return resourceResolver.getResources(location);
        } catch (IOException e) {
            return new Resource[0];
        }
    }

	public String[] getMappersLocations() {
		return mappersLocations;
	}

	public void setMappersLocations(String[] mappersLocations) {
		this.mappersLocations = mappersLocations;
	}

	public String getDialect() {
		return dialect;
	}

	public void setDialect(String dialect) {
		this.dialect = dialect;
	}

	public JdbcType getJdbcTypeForNull() {
		return jdbcTypeForNull;
	}

	public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) {
		this.jdbcTypeForNull = jdbcTypeForNull;
	}

	public Snowflake getSnowflake() {
		return snowflake;
	}

	public void setSnowflake(Snowflake snowflake) {
		this.snowflake = snowflake;
	}
	
	public class Snowflake {
		
		/**
		 * 范围：5~10
		 */
		private long workIdBits = 5L;
		
		/**
		 * 范围：0~根据workIdBits变化
		 */
		private long workId;

		private long epoch = SnowflakeIdGenerator.DEFAULT_EPOCH;
		
		public long getWorkId() {
			return workId;
		}

		public void setWorkId(long workId) {
			this.workId = workId;
		}

		public long getWorkIdBits() {
			return workIdBits;
		}

		public void setWorkIdBits(long workIdBits) {
			this.workIdBits = workIdBits;
		}

		public long getEpoch() {
			return epoch;
		}

		public void setEpoch(long epoch) {
			this.epoch = epoch;
		}
		
	}

}
